/**
 * Test SDL 1.3 speed
 */
#include "SDL.h"
#include <time.h>
#include <math.h>
#include <stdlib.h>

#define WINDOW_WIDTH (1024)
#define WINDOW_HEIGHT (768)
#define BALL_IMG "life.bmp"

#define BRICK_AREA_X (112)
#define BRICK_AREA_Y (84)
#define BRICK_AREA_W (800)
#define BRICK_AREA_H (600)
#define BRICK_W (16)
#define BRICK_H (15)
#define BALL_W (32)
#define BALL_H (32)

SDL_WindowID win;
SDL_TextureID ball;
int bricks[50][40];

static
void
quit (int rc) {
  exit(rc);
}

static
void init () {
  win = SDL_CreateWindow("SDL 1.3 bounce test",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED,
      WINDOW_WIDTH, WINDOW_HEIGHT,
      //SDL_WINDOW_FULLSCREEN|
      SDL_WINDOW_SHOWN);
  if (!win) {
    quit(EXIT_FAILURE);
  }
  srandom(time(0));
}

static
void loadResources () {
  SDL_Surface* ball_surf = SDL_LoadBMP(BALL_IMG);
  if (ball_surf == NULL) {
    fprintf(stderr,"Couldn't load image file: %s\n", BALL_IMG);
    quit(EXIT_FAILURE);
  }

  ball = SDL_CreateTextureFromSurface(0, ball_surf);

  if (!ball) {
    fprintf(stderr,"Unable to create texture from image file: %s\n", BALL_IMG);
    fprintf(stderr,"SDL said: %s\n", SDL_GetError());
    SDL_FreeSurface(ball_surf);
    quit(EXIT_FAILURE);
  }
  // Surface not needed anymore
  SDL_FreeSurface(ball_surf);
}

static
void freeResources () {
  SDL_DestroyRenderer(win);
}

static
void renderBricks () {
  int i, j, x, y;
  SDL_Rect rect = {-1, -1, BRICK_W, BRICK_H};

  SDL_SetRenderDrawColor(0x00,0x00,0x00,0xFF);
  SDL_RenderRect(NULL);
  
  for (j = 0, y = BRICK_AREA_Y; y < BRICK_AREA_Y+BRICK_AREA_H; y+=BRICK_H, j++) {
    for (i = 0, x = BRICK_AREA_X; x < BRICK_AREA_X+BRICK_AREA_W; x+=BRICK_W, i++) {
      if (bricks[i][j]) {
        SDL_SetRenderDrawColor(random() % 0xFF,
            random() % 0xFF,
            random() % 0xFF,
            0xFF);
      }
      else {
        SDL_SetRenderDrawColor(0x00,0x00,0x00,0xFF);
      }
      rect.x = x;
      rect.y = y;
      SDL_RenderRect(&rect);
    }
  }
}

static
void initBricks () {
  int i, j;

  for (j = 0; j < 40; j++) {
    for (i = 0; i < 50; i++) {
      if ((float)random()/(float)RAND_MAX < 0.5f) {
        bricks[i][j] = 0;
        continue;
      }
      bricks[i][j] = 1;
    }
  }
  renderBricks();
}

static
void ManageCollisions (float x, float y, float* dx, float* dy) {
  float nextx = x+*dx;
  float nexty = y+*dy;
  int idx;
  int idy;
  int nextidx;
  int nextidy;
  /* Check out of window */
  if ((nextx < 0.f) || (nextx+BALL_W >= WINDOW_WIDTH)) {
    *dx = -*dx;
  }
  if ((nexty < 0.f) || (nexty+BALL_H >= WINDOW_HEIGHT)) {
    *dy = -*dy;
  }
  /* Check brick collision:
   * Use grid coordinates. */
  float hotpoints[4][2] = {
    {x,y},
    {x+BALL_W,y},
    {x,y+BALL_H},
    {x+BALL_W,y+BALL_H}
  };
  float nexthotpoints[4][2] = {
    {nextx, nexty},
    {nextx+BALL_W,nexty},
    {nextx,nexty+BALL_H},
    {nextx+BALL_W,nexty+BALL_H}
  };

  int k;
  for (k = 0; k < 4; k++) {
    idx = (int)/*trunc*/((hotpoints[k][0] - (float)BRICK_AREA_X) / (float)BRICK_W);
    idy = (int)/*trunc*/((hotpoints[k][1] - (float)BRICK_AREA_Y) / (float)BRICK_H);
    nextidx = (int)trunc((nexthotpoints[k][0] - (float)BRICK_AREA_X) / (float)BRICK_W);
    nextidy = (int)trunc((nexthotpoints[k][1] - (float)BRICK_AREA_Y) / (float)BRICK_H);

    printf ("nextidx: %d, nextidy: %d\n", nextidx, nextidy);

    if ((nextidx < 0) || (nextidy < 0)) {
      return;
    }
    if ((nextidx >= 50) || (nextidy >= 40)) {
      return;
    }

    if (bricks[nextidx][nextidy]) {
      bricks[nextidx][nextidy] = 0;
      /* Adjust direction */
      if (nextidx != idx) {
        *dx = -*dx;
      }
      if (nextidy != idy) {
        *dy = -*dy;
      }
    }
  }
}

static
void bounce () {
  int w;
  int h;
  SDL_QueryTexture(ball,NULL,NULL,&w,&h);
  SDL_Rect position = { 0, 0, w, h };
  float x = position.x;
  float y = position.y;
  float angle = 0.f;
  float dx = 1.f;
  float dy = 1.f;

  SDL_Event evt;

  /* Generate a random initial direction */
  angle = 2.f * (double)M_PI * ((double)random() / (double)RAND_MAX);
  dx = cos(angle);
  dy = sin(angle);

  int done = 0;

  do {
    SDL_SetRenderDrawColor(0x00,0x00,0x00,0xFF);
    SDL_RenderRect(NULL);
    renderBricks();
    
    SDL_RenderCopy(ball,NULL,&position);
    SDL_RenderPresent();
    //SDL_Delay(1);
    ManageCollisions(x,y,&dx,&dy);
    
    //SDL_RenderRect(&position);
    
    x += dx;
    y += dy;
    position.x = (int)x;
    position.y = (int)y;

    while (SDL_PollEvent(&evt)) {
      if (evt.type == SDL_QUIT) {
        done = 1;
        break;
      }
      if (evt.type == SDL_KEYDOWN) {
        done = 1;
        break;
      }
    }
  }while(!done);
}


int main (int argc, char **argv) {
  init();
  loadResources();
  initBricks();
  bounce();
  freeResources();
  quit(EXIT_SUCCESS);
  return 0;
}

